package com.ysd.lis.service.lab.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.ysd.common.Result;
import com.ysd.lis.entity.PubEmployee;
import com.ysd.lis.entity.SysOrgDepartment;
import com.ysd.lis.entity.SysUser;
import com.ysd.lis.entity.lab.LabItemDict;
import com.ysd.lis.entity.lab.LabMaininfo;
import com.ysd.lis.entity.lab.LabRptGroup;
import com.ysd.lis.entity.lab.LabRptresult;
import com.ysd.lis.mapper.lab.LabItemDictMapper;
import com.ysd.lis.mapper.lab.LabMaininfoMapper;
import com.ysd.lis.mapper.lab.LabRptGroupMapper;
import com.ysd.lis.mapper.lab.LabRptresultMapper;
import com.ysd.lis.request.lab.GetPositiveReportDto;
import com.ysd.lis.request.lab.GetPositiveReportItemDto;
import com.ysd.lis.request.lab.GetPositiveReportResponseDto;
import com.ysd.lis.service.SysBasDictDetailService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class LabMaininfoServiceQueryImpl extends ServiceImpl<LabItemDictMapper, LabItemDict> {

    @Autowired
    LabRptGroupMapper labRptGroupMapper;
    @Autowired
    LabMaininfoMapper labMaininfoMapper;
    @Autowired
    SysBasDictDetailService sysBasDictDetailService;
    @Autowired
    LabRptresultMapper labRptresultMapper;

    /*阳性报表*/
    public Result getPositiveReports(GetPositiveReportDto input) {
        boolean multiConditions = !BeanUtil.isEmpty(input.getMultiConditions()) && input.getMultiConditions() == 1;

        List<String> rptGroups = new ArrayList<>();
        List<String> itemNos = new ArrayList<>();
        if (multiConditions) {
            if (input.getCondOptions().isEmpty()) {
                return Result.fail("请补充多项查询条件");
            }

            rptGroups = input.getCondOptions().isEmpty() ? null : input.getCondOptions().stream().map(GetPositiveReportItemDto::getRptGroup).distinct().collect(Collectors.toList());

            itemNos = input.getCondOptions().isEmpty() ? null : input.getCondOptions().stream().map(GetPositiveReportItemDto::getItemNo).distinct().collect(Collectors.toList());
        } else {
            if (StringUtils.isNotBlank(input.getRptGroup())) {
                rptGroups.add(input.getRptGroup());
            }

            if (!input.getItemNos().isEmpty()) {
                itemNos.addAll(input.getItemNos());
            }
        }

        MPJLambdaWrapper<LabRptresult> rptrQuery = new MPJLambdaWrapper<>();


        MPJLambdaWrapper<LabMaininfo> miQuery = new MPJLambdaWrapper<>();
        miQuery.selectAll(LabMaininfo.class);
        miQuery.eq(LabMaininfo::getDelFlag, 0);
        miQuery.selectAs("reqdoc", PubEmployee::getName, LabMaininfo::getReqDoctorNa);
        miQuery.selectAs("tstdoc", SysUser::getRealname, LabMaininfo::getTestDoctorNa);
        miQuery.selectAs("rptgrp", LabRptGroup::getRptGroupName, LabMaininfo::getRptGroupNa);
        miQuery.selectAs("reqdep", SysOrgDepartment::getName, LabMaininfo::getReqDeptNa);
        List<String> sampleNos = new ArrayList<>();
        if (StringUtils.isNotBlank(input.getSampleNo())) {
            sampleNos = getCodeRangeList(input.getSampleNo());
            miQuery.in(LabMaininfo::getSampleNo, sampleNos);
        }

        if (!BeanUtil.isEmpty(input.getSampledaS())) {
            Timestamp timestamp = new Timestamp(input.getSampledaS().getTime());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = sdf.format(timestamp);
            Timestamp startTime = Timestamp.valueOf(formattedDate + " 00:00:00");
            miQuery.ge(LabMaininfo::getSampleda, startTime);
            rptrQuery.ge(LabRptresult::getSampleda, startTime);
        }
        if (!BeanUtil.isEmpty(input.getSampledaE())) {
            Timestamp timestamp = new Timestamp(input.getSampledaE().getTime());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String formattedDate = sdf.format(timestamp);
            Timestamp endTime = Timestamp.valueOf(formattedDate + " 23:59:59");
            miQuery.le(LabMaininfo::getSampleda, endTime);
            rptrQuery.le(LabRptresult::getSampleda, endTime);
        }

        if (!rptGroups.isEmpty()) {
            miQuery.in(LabMaininfo::getRptGroup, rptGroups);
        }

        if (!itemNos.isEmpty()) {
            String itemNoStr = itemNos.isEmpty() ? "!@#QWE" : itemNos.size() == 1 ? itemNos.get(0) : itemNos.stream().collect(Collectors.joining("','"));
            miQuery.exists("select 1 from LAB_RPTRESULT rptr where rptr.RPT_GROUP=t.RPT_GROUP and rptr.SAMPLE_NO=t.SAMPLE_NO and CONVERT(nvarchar(10),rptr.SAMPLEDA,21)=CONVERT(nvarchar(10),t.SAMPLEDA,21) and rptr.DEL_FLAG=0 and rptr.ITEM_NO in ('" + itemNoStr + "')");
        }

        /*病人类型*/
        if (StringUtils.isNotBlank(input.getPatType())) {
            miQuery.eq(LabMaininfo::getPatType, input.getPatType());
        }

        /*样本类型*/
        if (StringUtils.isNotBlank(input.getSampleType())) {
            miQuery.eq(LabMaininfo::getSampleType, input.getSampleType());
        }

        /*查询状态：1全部 2未审核 3 初审 4审核*/
        if (StringUtils.isNotBlank(input.getStatus()) && "2".equals(input.getStatus())) {
            miQuery.ne(LabMaininfo::getIsChk, new BigDecimal(2));
        }
        if (StringUtils.isNotBlank(input.getStatus()) && "3".equals(input.getStatus())) {
            miQuery.ne(LabMaininfo::getIsChk, new BigDecimal(1));
        }
        if (StringUtils.isNotBlank(input.getStatus()) && "4".equals(input.getStatus())) {
            miQuery.ne(LabMaininfo::getIsChk, new BigDecimal(2));
        }

        /*申请科室*/
        if (StringUtils.isNotBlank(input.getReqDept())) {
            miQuery.eq(LabMaininfo::getReqDept, input.getReqDept());
        }

        /*条码号*/
        if (StringUtils.isNotBlank(input.getReqNo())) {
            miQuery.eq(LabMaininfo::getReqNo, input.getReqNo());
        }

        /*性别*/
        if (StringUtils.isNotBlank(input.getSex())) {
            miQuery.eq(LabMaininfo::getSex, input.getSex());
        }

        /*申请号*/
        if (StringUtils.isNotBlank(input.getBarCode())) {
            miQuery.eq(LabMaininfo::getRemark1, input.getBarCode());
        }

        /*诊断*/
        if (StringUtils.isNotBlank(input.getDiagnose())) {
            miQuery.eq(LabMaininfo::getDiagnose, input.getDiagnose());
        }

        /*申请目的*/
        if (StringUtils.isNotBlank(input.getReqPurpose())) {
            miQuery.eq(LabMaininfo::getReqPurpose, input.getReqPurpose());
        }

        /*筛选无病人姓名数据*/
        if (BeanUtil.isNotEmpty(input.getFilterNullName()) && input.getFilterNullName() == 1) {
            miQuery.ne(LabMaininfo::getPatNa, "");
            miQuery.isNotNull(LabMaininfo::getPatNa);
        }
        miQuery.leftJoin(PubEmployee.class, "reqdoc", p -> p.eq(PubEmployee::getCode, LabMaininfo::getReqDoctor).and(m -> m.eq(PubEmployee::getDelFlag, 0)));
        miQuery.leftJoin(SysUser.class, "tstdoc", p -> p.eq(SysUser::getUsername, LabMaininfo::getTestDoctor).and(m -> m.eq(SysUser::getDelFlag, 0)));
        miQuery.leftJoin(LabRptGroup.class, "rptgrp", p -> p.eq(LabRptGroup::getRptGroup, LabMaininfo::getRptGroup).and(m -> m.eq(LabRptGroup::getDelFlag, 0)));
        miQuery.leftJoin(SysOrgDepartment.class, "reqdep", p -> p.eq(SysOrgDepartment::getCode, LabMaininfo::getReqDept).and(m -> m.eq(SysOrgDepartment::getDelFlag, 0)));
        List<LabMaininfo> miList = labMaininfoMapper.selectList(miQuery);

        if (miList.isEmpty()) {
            return Result.succ(1, "成功", null);
        }
        List<String> samplenos = miList.isEmpty() ? null : miList.stream().map(LabMaininfo::getSampleNo).distinct().collect(Collectors.toList());
        List<String> rptGroupArrs = miList.isEmpty() ? null : miList.stream().map(LabMaininfo::getRptGroup).distinct().collect(Collectors.toList());


        rptrQuery.selectAll(LabRptresult.class);
        rptrQuery.eq(LabRptresult::getDelFlag, 0);
        if (!rptGroupArrs.isEmpty()) {
            rptrQuery.in(LabRptresult::getRptGroup, rptGroupArrs);
            //String rptGroupsStr = miList.isEmpty() ? "!@#QWE" : miList.stream().map(p -> p.getRptGroup()).distinct().collect(Collectors.joining("','"));
            //rptrQuery.exists("select 1 from LAB_RPTRESULT where RPT_GROUP in ('" + rptGroupsStr + "')");
        }
        if (!samplenos.isEmpty()) {
            rptrQuery.in(LabRptresult::getSampleNo, samplenos);
            //String sampleNosStr = miList.isEmpty() ? "!@#QWE" : miList.stream().map(p -> p.getSampleNo()).distinct().collect(Collectors.joining("','"));
            //rptrQuery.exists("select 1 from LAB_RPTRESULT where SAMPLE_NO in ('" + sampleNosStr + "')");
        }

        if (!input.getItemNos().isEmpty()) {
            rptrQuery.in(LabRptresult::getItemNo, input.getItemNos());
            //String sampleNosStr = miList.isEmpty() ? "!@#QWE" : miList.stream().map(p -> p.getSampleda()).collect(Collectors.joining("','"));
            //String itemNosStr = input.getItemNos().isEmpty() ? "!@#QWE" : input.getItemNos().stream().filter(StringUtils::isNotBlank).collect(Collectors.joining("','"));
            //rptrQuery.exists("select 1 from LAB_RPTRESULT where ITEM_NO in ('" + itemNosStr + "')");
        }

        if (!itemNos.isEmpty()) {
            rptrQuery.in(LabRptresult::getItemNo, itemNos);
        }

        List<LabRptresult> _rptresultList = labRptresultMapper.selectList(rptrQuery);

        List<GetPositiveReportResponseDto> resList = new ArrayList<>();
        List<Map<String, Object>> sexList = (List<Map<String, Object>>) sysBasDictDetailService.getSysBasDictList("Sex").getData();
        for (LabMaininfo m : miList) {
            List<LabRptresult> rptresultList = _rptresultList.isEmpty() ? new ArrayList<>() : _rptresultList.stream().filter(p -> p.getRptGroup().equals(m.getRptGroup()) && p.getSampleNo().equals(m.getSampleNo()) && p.getSampleda().equals(m.getSampleda())).collect(Collectors.toList());

            for (LabRptresult op : rptresultList) {
                GetPositiveReportResponseDto itm = new GetPositiveReportResponseDto();
                itm.setMaininfoId(m.getId());
                itm.setBedNo(m.getBedNo());
                itm.setTestDoctorNa(m.getTestDoctorNa());
                itm.setFeeType(m.getFeeType());
                itm.setRptGroup(m.getRptGroup());
                itm.setRptGroupNa(m.getRptGroupNa());
                itm.setSampleNo(m.getSampleNo());
                itm.setSampleda(m.getSampleda());
                String ageStr = "";
                if (BeanUtil.isNotEmpty(m.getAge())) {
                    ageStr += m.getAge().toString();
                    if (BeanUtil.isNotEmpty(m.getAgeUnit())) {
                        ageStr += m.getAgeUnit();
                    }
                }
                if (BeanUtil.isNotEmpty(m.getSecAge())) {
                    ageStr += m.getSecAge().toString();
                    if (BeanUtil.isNotEmpty(m.getSecAgeUnit())) {
                        ageStr += m.getSecAgeUnit();
                    }
                }
                itm.setItemNo(op.getItemNo());
                itm.setItemNa(op.getItemNa());
                itm.setRawResult(op.getRawData());
                itm.setResult(op.getTestResult());
                try {
                    if (StringUtils.isNotBlank(op.getTestResult()) && op.getTestResult().matches("-?\\d+(\\.\\d+)?")) {
                        itm.setNumResult(Double.parseDouble(op.getTestResult()));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                itm.setAgeStr(ageStr);
                itm.setPatNa(m.getPatNa());
                itm.setPatNo(m.getPatNo());
                itm.setReqDept(m.getReqDept());
                itm.setReqDoctor(m.getReqDoctor());
                itm.setReqNo(m.getReqNo());
                itm.setReqPurpose(m.getReqPurpose());
                itm.setReqDoctorNa(m.getReqDoctorNa());
                itm.setReqDeptNa(m.getReqDeptNa());
                itm.setTestDoctor(m.getTestDoctor());
                itm.setSex(m.getSex());
                sexList.stream().filter(a -> a.get("code").equals(m.getSex())).findFirst().ifPresent(stringObjectMap -> itm.setSexNa((String) stringObjectMap.get("name")));
                itm.setInstrCode(op.getInstrCode());
                itm.setInstrNa(op.getInstrNa());
                resList.add(itm);

            }
        }

        List<Predicate<GetPositiveReportResponseDto>> dynamicPredicates = new ArrayList<>();
        if (!multiConditions) {
            Predicate<GetPositiveReportResponseDto> p1 = null;
            Predicate<GetPositiveReportResponseDto> p2 = null;
            Predicate<GetPositiveReportResponseDto> p3 = null;
            if (BeanUtil.isNotEmpty(input.getLeVal()) && !resList.isEmpty()) {
                p2 = p -> {
                    if (BeanUtil.isNotEmpty(p.getNumResult())) {
                        System.out.println("值：" + p.getNumResult() + ",小于：" + input.getLeVal() + ",值<" + input.getLeVal() + "[" + (p.getNumResult() < input.getLeVal()) + "]");
                    }
                    return BeanUtil.isNotEmpty(p.getNumResult()) && p.getNumResult() < input.getLeVal();
                };
                p3 = p2;
            }
            if (BeanUtil.isNotEmpty(input.getGtVal()) && !resList.isEmpty()) {
                p2 = p -> {
                    if (BeanUtil.isNotEmpty(p.getNumResult())) {
                        System.out.println("值：" + p.getNumResult() + ",大于：" + input.getGtVal() + ",值>" + input.getGtVal() + "[" + (p.getNumResult() > input.getGtVal()) + "]");
                    }
                    return BeanUtil.isNotEmpty(p.getNumResult()) && p.getNumResult() > input.getGtVal();
                };
                p3 = p3 == null ? p2 : p3.or(p2);
            }

            boolean txtValLikeFilter = BeanUtil.isNotEmpty(input.getTxtValLikeFilter()) && input.getTxtValLikeFilter() == 1;

            if (StringUtils.isNotBlank(input.getTxtValEq()) && !resList.isEmpty()) {
                if (txtValLikeFilter) {
                    p2 = p -> BeanUtil.isNotEmpty(p.getResult()) && input.getTxtValEq().contains(p.getResult());//p.getResult().contains(input.getTxtValEq());
                } else {
                    p2 = p -> BeanUtil.isNotEmpty(p.getResult()) && p.getResult().equals(input.getTxtValEq());
                }
                p3 = p3 == null ? p2 : p3.or(p2);
            }

            if (StringUtils.isNotBlank(input.getTxtValNotEq()) && !resList.isEmpty()) {
                if (txtValLikeFilter) {
                    p2 = p -> BeanUtil.isEmpty(p.getResult()) || !p.getResult().contains(input.getTxtValEq());
                } else {
                    p2 = p -> BeanUtil.isEmpty(p.getResult()) || !p.getResult().equals(input.getTxtValEq());
                }
                p3 = p3 == null ? p2 : p3.or(p2);
            }
            p1 = p3;
            if (p1 != null) {
                System.out.println("执行前条数:" + resList.size());
                resList = resList.stream().filter(p1::test).collect(Collectors.toList());
                System.out.println("执行后条数:" + resList.size());
            }
        }

        if (multiConditions) {
            //是否满足所有条件
            boolean enableAllConds = BeanUtil.isNotEmpty(input.getEnableAllConds()) && input.getEnableAllConds() == 1;
            Predicate<GetPositiveReportResponseDto> exp = null;
            for (GetPositiveReportItemDto mm : input.getCondOptions()) {
                Predicate<GetPositiveReportResponseDto> exp1 = null;
                Predicate<GetPositiveReportResponseDto> expTemp = null;
                if (StringUtils.isNotBlank(mm.getRptGroup()) && !resList.isEmpty()) {
                    expTemp = p -> {
                        if (BeanUtil.isEmpty(p)) {
                            return false;
                        }
                        if (BeanUtil.isNotEmpty(p.getRptGroup())) {
                            System.out.println("值：" + p.getRptGroup() + ",大于：");
                        }
                        return StringUtils.isNotBlank(p.getRptGroup()) && p.getRptGroup().equals(mm.getRptGroup());
                    };
                    exp1 = expTemp;
                }
                if (StringUtils.isNotBlank(mm.getItemNo()) && !resList.isEmpty()) {
                    expTemp = p -> {
                        if (BeanUtil.isEmpty(p)) {
                            return false;
                        }
                        if (BeanUtil.isNotEmpty(p.getItemNo())) {
                            System.out.println("值：" + p.getItemNo() + ",大于：" + mm.getItemNo() + ",值>" + mm.getItemNo());
                        }
                        return StringUtils.isNotBlank(p.getItemNo()) && p.getItemNo().equals(mm.getItemNo());
                    };
                    exp1 = exp1 == null ? expTemp : exp1.and(expTemp);
                }

                Predicate<GetPositiveReportResponseDto> exp3Temp = null;
                if (BeanUtil.isNotEmpty(mm.getLeVal()) && !resList.isEmpty()) {
                    expTemp = p -> {
                        if (BeanUtil.isEmpty(p)) {
                            return false;
                        }
                        if (BeanUtil.isNotEmpty(p.getNumResult())) {
                            System.out.println("值：" + p.getNumResult() + ",小于：" + mm.getLeVal() + ",值<" + mm.getLeVal() + "[" + (p.getNumResult() < mm.getLeVal()) + "]");
                        }
                        return BeanUtil.isNotEmpty(p.getNumResult()) && p.getNumResult() < mm.getLeVal();
                    };
                    exp3Temp = expTemp;
                }
                if (BeanUtil.isNotEmpty(mm.getGtVal()) && !resList.isEmpty()) {
                    expTemp = p -> {
                        if (BeanUtil.isNotEmpty(p.getNumResult())) {
                            System.out.println("值：" + p.getNumResult() + ",大于：" + mm.getGtVal() + ",值>" + mm.getGtVal() + "[" + (p.getNumResult() > mm.getGtVal()) + "]");
                        }
                        return BeanUtil.isNotEmpty(p.getNumResult()) && p.getNumResult() > mm.getGtVal();
                    };
                    exp3Temp = exp3Temp == null ? expTemp : exp3Temp.or(expTemp);
                }
                if (StringUtils.isNotBlank(mm.getTxtValEq()) && !resList.isEmpty()) {
                    expTemp = p -> {
                        if (BeanUtil.isNotEmpty(p.getResult())) {
                            System.out.println("文字结果是否相等[" + p.getResult().equals(mm.getTxtValEq()) + "]");
                        }
                        return BeanUtil.isNotEmpty(p.getResult()) && p.getResult().equals(mm.getTxtValEq());
                    };
                    exp3Temp = exp3Temp == null ? expTemp : exp3Temp.or(expTemp);
                }
                exp1 = exp1 == null ? exp3Temp : exp3Temp == null ? null : exp1.and(exp3Temp);

                if (enableAllConds) {
                    exp = exp == null ? exp1 : exp1 == null ? null : exp.and(exp1);
                } else {
                    exp = exp == null ? exp1 : exp1 == null ? null : exp.or(exp1);
                }
            }
            if (exp != null) {
                resList = resList.stream().filter(exp::test).collect(Collectors.toList());
            }
        }

        if (BeanUtil.isNotEmpty(input.getOrderDescByScheduleDate()) && input.getOrderDescByScheduleDate() == 1) {
            resList = resList.stream().sorted(Comparator.comparing(GetPositiveReportResponseDto::getSampleda, Comparator.nullsLast(Comparator.reverseOrder())).thenComparing(GetPositiveReportResponseDto::getPatNo, Comparator.nullsLast(Comparator.reverseOrder())).thenComparing(GetPositiveReportResponseDto::getRptGroupNa, Comparator.nullsLast(Comparator.reverseOrder())).thenComparing(GetPositiveReportResponseDto::getSampleNo, Comparator.nullsLast(Comparator.reverseOrder()))).collect(Collectors.toList());
        } else {
            resList = resList.stream().sorted(Comparator.comparing(GetPositiveReportResponseDto::getSampleda, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(GetPositiveReportResponseDto::getPatNo, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(GetPositiveReportResponseDto::getRptGroupNa, Comparator.nullsLast(Comparator.naturalOrder())).thenComparing(GetPositiveReportResponseDto::getSampleNo, Comparator.nullsLast(Comparator.naturalOrder()))).collect(Collectors.toList());
        }

        return Result.succ(1, "成功", resList);
    }

    private static List<String> getCodeRangeList(String code) {
        List<String> codes = new ArrayList<>();
        int sortCodeLen = 20;
        code = code.replace("，", ",");
        code = code.replace("—", "-");
        String[] codeArray = code.split(",");
        for (String c : codeArray) {
            if (c.contains("-")) {
                int count = 0;
                int len = 0;
                String[] range = c.split("-");

                if (range[0].length() == range[1].length()) {
                    len = range[0].length();
                }
                String codeMin = range[0];
                String codeMax = range[1];

                String currentCode = codeMin;

                codes.add(range[0]);
                do {
                    currentCode = codeAutoIncrement(currentCode);//codeAutoIncrement(currentCode).substring(sortCodeLen);
                    codes.add(currentCode);
                    count += 1;

                    if (count > 10000) {
                        break;
                    }

                } while (!currentCode.equalsIgnoreCase(codeMax));

            } else {
                codes.add(c);
            }
        }

        return codes;
    }

    private static String codeAutoIncrement(String minCode) {
        char[] charArr = minCode.toCharArray();
        String str = "";
        for (int i = charArr.length - 1; i >= 0; i--) {
            if (Character.isDigit(charArr[i])) {
                str = charArr[i] + str;
            } else {
                break;
            }
        }
        int curInt = Integer.parseInt(str);
        String _str = String.valueOf(curInt + 1);
        if (_str.length() < minCode.length()) {
            _str = minCode.substring(0, minCode.length() - str.length()) + _str;
        }
        return _str;
    }
}
